package ltd.nullpointer.frontend.service;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.boot2.core.utils.BeanUtils;
import com.boot2.core.utils.DateUtil;
import com.boot2.core.utils.HttpsClient;
import com.boot2.core.utils.ThreadPoolTaskExecutorUtil;
import lombok.extern.apachecommons.CommonsLog;
import ltd.nullpointer.frontend.dao.SensorDataDao;
import ltd.nullpointer.frontend.dao.SensorRainDataDao;
import ltd.nullpointer.frontend.dao.SensorRainDataDetailDao;
import ltd.nullpointer.frontend.model.dto.up.SensorData1BDto;
import ltd.nullpointer.frontend.model.entity.SensorRainData;
import ltd.nullpointer.frontend.model.entity.SensorRainDataDetail;
import ltd.nullpointer.tcp.server.conf.ThingsNpProperties;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author zhangweilin
 * @Description: xxxxx
 * @date 2019/12/15
 */
@Service
@CommonsLog
public class SensorRainDataService {

    @Autowired
    SensorRainDataDao sensorRainDataDao;

    @Autowired
    SensorDataDao sensorDataDao;

    @Autowired
    SensorRainDataDetailDao sensorRainDataDetailDao;

    @Autowired
    ThingsNpProperties thingsNpProperties;

    @Autowired
    NpAtrributeKvService npAtrributeKvService;

    ThreadPoolTaskExecutor threadPoolTaskExecutorUtil = ThreadPoolTaskExecutorUtil.createThreadPoolTaskExecutor();

    /**
     * 持久化沉降数据
     *
     * @param sensorRainData
     */
    @Async
    public void saveSensorRainData(SensorRainData sensorRainData, List<SensorData1BDto.Data> dataList) {
        List<SensorRainDataDetail> sensorRainDataDetailList = null;
        if (CollectionUtils.isNotEmpty(dataList)) {
            sensorRainDataDetailList = new ArrayList<>();
            for (SensorData1BDto.Data data : dataList) {
                SensorRainDataDetail sensorRainDataDetail = new SensorRainDataDetail();
                BeanUtils.copyProperties(data, sensorRainDataDetail);
                sensorRainDataDetailList.add(sensorRainDataDetail);
            }
        }
        save(sensorRainData, sensorRainDataDetailList);
    }

//    @Async
//    public void saveSensorData(SensorData sensorData) {
//        sensorDataDao.saveAndFlush(sensorData);
//    }

    /**
     * 保存雨量数据和明细
     *
     * @param sensorRainData
     * @param sensorRainDataDetailList
     */
    public void save(SensorRainData sensorRainData, List<SensorRainDataDetail> sensorRainDataDetailList) {
        String sensorNo = sensorRainData.getSensorNo();
        SensorRainData sensorRainData1 = sensorRainDataDao.findBySensorNo(sensorNo);
        if (sensorRainData1 == null) {
            sensorRainData.setCreateTime();
            sensorRainDataDao.saveAndFlush(sensorRainData);
        } else {
            BeanUtils.copyProperties(sensorRainData, sensorRainData1);
            sensorRainDataDao.saveAndFlush(sensorRainData1);
            sensorRainData = sensorRainData1;
        }

        if (CollectionUtils.isNotEmpty(sensorRainDataDetailList)) {
            for (SensorRainDataDetail sensorRainDataDetail : sensorRainDataDetailList) {
                boolean exists = sensorRainDataDetailDao.existsBySensorNoAndMeasuringDate(sensorNo, sensorRainDataDetail.getMeasuringDate());
                if (exists) {
                    log.warn("忽略重复检测数据，sensorNo:"+sensorRainDataDetail.getSensorNo()+" ,measuringDate: "+DateUtil.formatDate(sensorRainDataDetail.getMeasuringDate()));
                    continue;
                }

                sensorRainDataDetail.setSensorRainData(sensorRainData);
                Date measuringDate = sensorRainDataDetail.getMeasuringDate();
                int year = DateUtil.getYear(measuringDate);
                int month = DateUtil.getMonth(measuringDate);
                int day = DateUtil.getDay(measuringDate);
                int hour = DateUtil.getHour(measuringDate);
                int min = DateUtil.getMin(measuringDate);
                sensorRainDataDetail.setYear(year);
                sensorRainDataDetail.setMonth(month);
                sensorRainDataDetail.setDay(day);
                sensorRainDataDetail.setHour(hour);
                sensorRainDataDetail.setMin(min);
                sensorRainDataDetail.setSensorNo(sensorNo);
                sensorRainDataDetail.setCreateTime();
                sensorRainDataDetail.setOriginalMeasure(sensorRainDataDetail.getMeasurement());

                //在此处利用公式修正测量值
                Map<String, Double> allAttributeKv = npAtrributeKvService.selectAllAttributeKv(sensorRainData.getSensorNo());
                Double initialValue = allAttributeKv.get("initial_value") == null ? 0.0 : allAttributeKv.get("initial_value");
                Double height = allAttributeKv.get("height") == null ? 0.0 : allAttributeKv.get("height");
                Double depth = allAttributeKv.get("depth") == null ? 0.0 : allAttributeKv.get("depth");
                Double ratio = allAttributeKv.get("ratio") == null ? 1.0 : allAttributeKv.get("ratio");
                Double controlFlag = allAttributeKv.get("control_flag");
                if (controlFlag != null && controlFlag == 1) {
                    Double height2 = height - depth + ratio * (sensorRainDataDetail.getMeasurement().doubleValue() - initialValue);
                    sensorRainDataDetail.setMeasurement(new BigDecimal(height2));
                }

                String token = npAtrributeKvService.getTokenBySensorNo(sensorNo);
                String telemetryUrl = thingsNpProperties.getBaseHttpUrl() + String.format("%s/telemetry", token);

                String telemetryJson = JSONObject.toJSONString(sensorRainDataDetail, SerializerFeature.WriteDateUseDateFormat);
                threadPoolTaskExecutorUtil.submit(() -> {
                    HttpsClient.postJson(telemetryUrl, telemetryJson);
                });

                sensorRainDataDetailDao.saveAndFlush(sensorRainDataDetail);
            }
        }
    }
}
